﻿/*  ----------------------------------------------------------------------------
 *  DES-Release 2
 *  ----------------------------------------------------------------------------
 *  File:       ServerTask.cs
 *  Author:     nitinkoshy@gmail.com
 *  Source:     http://des.codeplex.com/
 *  ----------------------------------------------------------------------------
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DES.Common;
using System.Runtime.Serialization;
using System.Diagnostics;


namespace DES.Server.Service
{
    [DataContract]
    public class ServerTask
    {
        private Stack<DESServerInfo> _forwardedServerStack = new Stack<DESServerInfo>();

        public ServerTask()
        {
            ChildTasksCollected = false;
        }

        public ServerTask(ClientTask task):this()
        {
            Task = task;
        }

        [DataMember]
        public string ClientEndPoint
        {
            get;
            set;

        }

        [DataMember]
        public ClientTask Task
        {
            get;
            set;
        }


        [DataMember]
        public Stack<DESServerInfo> ForwardedServerStack
        {
            get
            {
                return _forwardedServerStack;
            }
            set
            {
                _forwardedServerStack = value;
            }
        }

        public int HoppedCount
        {
            get
            {
                return ForwardedServerStack.Count;
            }
        }

        public bool HasBeenForwarded
        {
            get
            {
                return ForwardedServerStack.Count > 1;//the first one being the default/first serverS
            }
        }


        public void MarkAsForwarded(DESServerInfo originatingServer)
        {
            Trace.Write(String.Format("[{0}]:", DateTime.Now.ToShortTimeString()));
            Trace.WriteLine(String.Format("Marking task {0} as forwarded from {1}", Task.Name, originatingServer.Id));

            if (ForwardedServerStack.Count == 0)//first one
                RootServer = originatingServer;

            lock (ForwardedServerStack)
            {
                ForwardedServerStack.Push(originatingServer);
                Trace.WriteLine(String.Format("{0}:ForwardStackDump MarkAsForwarded() For {1} is {2}", DateTime.Now.ToShortTimeString(), Task.Name, StackToCSV(ForwardedServerStack)));
            }

            
        }

        private string StackToCSV(Stack<DESServerInfo> stack)
        {
            string result = String.Empty;
            for (int i = 0; i < stack.Count; i++)
            {
                result += "/" + stack.ElementAt(i).Id;
            }
            return result;

            //convert to use stack.aggregate with a lambda?
        }

        public bool HasReachedRoot(DESServerService serverService)
        {
            return ((RootServer == null) || (RootServer.Id == serverService.ServerInfo.Id));
        }

        public bool HasReachedWaitingServer(DESServerService serverService)
        {
            return ((ChildTasksMarkedAtServer.Id == serverService.ServerInfo.Id));
        }


        public void MarkAsReceived()
        {
            Trace.Write(String.Format("[{0}]:", DateTime.Now.ToShortTimeString()));
            Trace.WriteLine(String.Format("Marking task {0} as received", Task.Name));


            if (ForwardedServerStack.Count > 0)
                lock (ForwardedServerStack)
                {
                    Trace.WriteLine(String.Format("{0}:ForwardStackDump MarkAsReceived() For {1} is {2}", DateTime.Now.ToShortTimeString(), Task.Name, StackToCSV(ForwardedServerStack)));
                    ForwardedServerStack.Pop();
                }
        }

        public DESServerInfo ImmediateParentServer
        {
            get
            {
                lock (ForwardedServerStack)
                {
                    return ForwardedServerStack.Peek();
                }
            }
        }

        /// <summary>
        /// the server from where the forwarding started.
        /// </summary>
        [DataMember]
        public DESServerInfo RootServer
        {
            get;
            set;

        }
        /// <summary>
        /// Indicates the server at which the child tasks got considered/marked for execution.
        /// Basically, this task would need to wait at the waiting gate of this server
        /// for its child tasks.
        /// </summary>
        [DataMember]
        public DESServerInfo ChildTasksMarkedAtServer
        {
            get;
            set;
        }

        [DataMember]
        public bool ChildTasksCollected
        {
            get;
            set;
        }



    }
}
